((name, root) => {
    
    const console = (function (root) {
        if (typeof root.imports === "undefined" || !Object.isSealed(root.imports)) {
            function imports(dependencies, callback) {
                const deps = [].concat(dependencies);
                addEventListener("import", _imports);
                function _imports() {
                    if (callback != null) {
                        if (deps.some(name => !root.imports.hasOwnProperty(name))) {
                            return;
                        }
                        removeEventListener("import", _imports);
                        const values = deps.map(name => root.imports[name]);
                        if (typeof requestIdleCallback === "function") {
                            requestIdleCallback(() => callback(...values), { timeout: 100 });
                        } else if (typeof setTimeout === "function") {
                            setTimeout(() => callback(...values));
                        } else {
                            callback(...values);
                        }
                    }
                }
                _imports();
            }

            root.imports = new Proxy(imports, {
                get: (target, prop) => target[prop],
                set: (target, prop, value) => {
                    if (target.hasOwnProperty(prop)) {
                        console.warn(`import: ${prop} has been replaced!`, { old: target[prop], new: value });
                    }
                    target[prop] = value;
                    dispatchEvent(new CustomEvent("import", { detail: { name, value } }));
                    return true;
                }
            });
            Object.defineProperty(root, "imports", {
                configurable: false,
                enumerable: false,
                writable: false,
            });
        }
        return new Proxy(root.console || console, {
            get: (target, prop) => target && target.debugs && target.debugs.some(x => x === name || x === "*") ? target[prop] : () => { },
        });
    })(root || this);

    function Dynamic(value) {
        const handler = {
            get(target, prop) {
                console.log("get", { target, prop });
                if (prop in target) {
                    return target[prop];
                }
                if (value == null) {
                    return Dynamic(value);
                }
                let val = value[prop];
                if (val == null) {
                    const key = Object.keys(value).find(key => key.toLowerCase() === prop.toLowerCase());
                    if (key != null) {
                        val = value[key];
                    }
                }
                return Dynamic(val);
            },
            ownKeys(target) {
                if (typeof value !== "object") {
                    return null;
                }
                return Reflect.ownKeys(value);
            },
            getOwnPropertyDescriptor(target, prop) {
                if (value == null) {
                    return null;
                }
                return Reflect.getOwnPropertyDescriptor(value, prop);
            },
            apply(target, thisArg, args) {
                console.log("apply", { target, thisArg, args });
                if (typeof value !== "function") {
                    return null;
                }
                return value.apply(thisArg.valueOf(), args);
            }
        };
        const obj = Object.assign(() => { }, {
            valueOf() {
                return value;
            },
            toString() {
                return JSON.stringify(value);
            },
            [Symbol.toPrimitive]: undefined,
            [Symbol.iterator]() {
                return function* () {
                    yield value;
                };
            },
            [Symbol.toStringTag]: name,
            toJSON() {
                return value;
            }
        });
        return new Proxy(obj, handler);
    }

    if (typeof window !== "undefined") {
        window[name] = Dynamic;
    }
    root.imports[name] = Dynamic;

})("Dynamic", this);
